package ai.connectfour.gui;

import java.awt.GridLayout;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Observable;
import java.util.Observer;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JOptionPane;

import ai.connectfour.Config;
import ai.connectfour.Controller;
import ai.connectfour.entities.CellState;
import ai.connectfour.entities.Player;
import ai.connectfour.entities.State;

public class Gui extends JFrame implements Observer, MouseListener{
	private static final long serialVersionUID = -390570070061130441L;

	private Controller controller;
	GameFieldImagePanel[][] connectFourPanels = new GameFieldImagePanel[Config.DIMENSION_ROWS][Config.DIMENSION_COLS];
	ChoiceImagePanel[] choicePanel = new ChoiceImagePanel[Config.DIMENSION_COLS];
	private boolean isPlayerTurn = !Config.MAX_STARTS;
	
	public Gui(Controller controller){
		super();
		this.controller = controller;
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setSize(Config.DIMENSION_COLS*100,(Config.DIMENSION_ROWS+1)*100);
		this.setTitle("Vier gewinnt!");
		this.setVisible(true);
		this.setResizable(false);
		
		BufferedImage redImage;
		BufferedImage yellowImage;
		BufferedImage arrowImage;
		try {
			redImage = ImageIO.read(new File(Config.RED_IMAGE_PATH));
			yellowImage = ImageIO.read(new File(Config.YELLOW_IMAGE_PATH));
			arrowImage = ImageIO.read(new File(Config.ARROW_IMAGE_PATH));
			
			this.setLayout(new GridLayout(Config.DIMENSION_ROWS+1,Config.DIMENSION_COLS));
			
			// Choice Field
			for(int col=0;col < Config.DIMENSION_COLS;col++){ 
				choicePanel[col] = new ChoiceImagePanel(col, arrowImage);
				choicePanel[col].addMouseListener(this);
				this.add(choicePanel[col]);
			}
			
			// Game Field
			for(int row=Config.DIMENSION_ROWS-1; row >= 0;row--){
				for(int col=0;col < Config.DIMENSION_COLS;col++){ 
					connectFourPanels[row][col] = new GameFieldImagePanel(row, col, redImage, yellowImage);
					connectFourPanels[row][col].addMouseListener(this);
					this.add(connectFourPanels[row][col]);
				}
			}
			
		} catch (IOException e) {
			e.printStackTrace();
			System.exit(-1);
		}
	}

	@Override
	public void update(Observable observable, Object argument){
		State currentState = (State) argument;
		CellState[][] field = currentState.getField();
		for(int i=0; i < field.length;i++){
			for(int j=0;j < field[i].length;j++){
				connectFourPanels[i][j].setCurrentState(currentState.getField()[i][j]);
				this.repaint();
			}
		}
		if(currentState.terminalTest() || this.isGameFull()){
			if(currentState.getWinner() == Player.MAX){
				JOptionPane.showMessageDialog(this, "Verloren", "Ok um nochmal zu spielen", JOptionPane.OK_OPTION);
				isPlayerTurn = true;
			}
			else if(currentState.getWinner() == Player.MIN){
				JOptionPane.showMessageDialog(this, "Gewonnen!", "Ok um nochmal zu spielen", JOptionPane.OK_OPTION);
				isPlayerTurn = false;
			}else{
				JOptionPane.showMessageDialog(this, "Unentschieden!", "Ok um nochmal zu spielen", JOptionPane.OK_OPTION);
				isPlayerTurn = !isPlayerTurn;
			}
			controller.resetGame();
		}
	}

	private boolean isGameFull() {
		for(int row=Config.DIMENSION_ROWS-1; row >= 0;row--){
			for(int col=0;col < Config.DIMENSION_COLS;col++){ 
				if(connectFourPanels[row][col].getCurrentState() == CellState.EMPTY){
					return false;
				}
			}
		}
		return true;
	}

	@Override
	public void mouseClicked(MouseEvent event) {
		if(event.getButton() == MouseEvent.BUTTON1){
			if(isPlayerTurn){
				try{
					ChoiceImagePanel clickedPanel = (ChoiceImagePanel) event.getSource();
					int col = clickedPanel.getCol();
					boolean isFull = true;
					for(int row=Config.DIMENSION_ROWS-1; row >= 0;row--){
						if(connectFourPanels[row][col].getCurrentState() == CellState.EMPTY){
							isFull = false;
							break;
						}
					}
					if(!isFull){
						controller.doPlayerTurn(clickedPanel.getCol());	
					}
					
				}catch(ClassCastException e){}
			}
		}else if(event.getButton() == MouseEvent.BUTTON3){
			if(isPlayerTurn){
				try{
					ChoiceImagePanel clickedPanel = (ChoiceImagePanel) event.getSource();
					controller.undoPlayerTurn(clickedPanel.getCol());
					
				}catch(ClassCastException e){}
			}
		}
	}

	@Override
	public void mouseEntered(MouseEvent event) {
		try{
			ChoiceImagePanel mouseOverPanel = (ChoiceImagePanel) event.getSource();
			mouseOverPanel.setMouseOver(true);	
			mouseOverPanel.repaint();
		}catch(ClassCastException e){}
	}

	@Override
	public void mouseExited(MouseEvent event) {
		try{
			ChoiceImagePanel mouseOverPanel = (ChoiceImagePanel) event.getSource();
			mouseOverPanel.setMouseOver(false);	
			mouseOverPanel.repaint();
		}catch(ClassCastException e){}
	}

	@Override
	public void mousePressed(MouseEvent event) {}

	@Override
	public void mouseReleased(MouseEvent event) {}
}
